package org.my.tcp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * netty 服务
 */
public class NettyServer {
    public static void main(String[] args) {
        /**
         *
         *  创建BossGroup 和 WorkerGroup
         * 说明:
         *  1. 创建连个线程组 bossGroup 和 workerGroup
         *  2. bossGroup只处理连接请求(accept), 真正的和客户端业务处理, 会交给workerGroup完成
         *  3. 两个都是无线循环
         *  4. bossGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数
         *  默认: 实际CPU核数 * 2
         *
         */
        EventLoopGroup bossGroup=new NioEventLoopGroup();
        EventLoopGroup workderGroup=new NioEventLoopGroup();

        ServerBootstrap serverBootstrap=new ServerBootstrap();
        serverBootstrap.group(bossGroup,workderGroup) //设置两个线程组
            .channel(NioServerSocketChannel.class) //使用NioServerSocketChannel作为服务器的通道实现
            .childOption(ChannelOption.SO_BACKLOG,1024) //设置线程队列等待连接个数
            .childOption(ChannelOption.SO_KEEPALIVE,true) //设置保持活动连接状态
            .childHandler(new ChannelInitializer<SocketChannel>() {
                /**
                 * 初始化通道
                 *  创建一个通道初始化对象(匿名对象)
                 *  给pipeline设置处理器
                 * @param socketChannel SocketChannel
                 * @throws Exception err
                 */
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline=socketChannel.pipeline();
                    //1.读超时，2，写超时，3.读写超时的时间设置，单位为秒，需要实现userEventTriggered方法在nettyServerHandler重写
                    pipeline.addLast(new IdleStateHandler(30,0,0));
                    //pipeline.addLast(new HeartBeatServerHandler());
                    //设置处理器
                    pipeline.addLast(new NettyServerHandler());
                }
            });
        try {
            ChannelFuture channelFuture = serverBootstrap.bind(40003).sync();
            System.out.println("监听40003端口");

            //通道关闭监听
            channelFuture.channel().closeFuture().sync();

        }catch(InterruptedException e){
            e.printStackTrace();
        }finally{
            bossGroup.shutdownGracefully();
            workderGroup.shutdownGracefully();
        }
    }
}
